﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Text;

namespace Savage.DotNetLibrary.DatabaseLibrary
{
    public class Logins
    {
        public Logins(string connectionString)
        {
            _sqlDataWrapper = new SqlDataWrapper(connectionString);
        }

        private SqlDataWrapper _sqlDataWrapper;

        /// <summary>
        /// Creates a new SQL Server login.
        /// </summary>
        /// <param name="loginName">The name of the login that is created.</param>
        /// <param name="password">The password for the login that is being created.</param>
        public void CreateLogin(string loginName, string password)
        {
            CreateLogin(loginName, password, false, null);
        }

        /// <summary>
        /// Creates a new SQL Server login.
        /// </summary>
        /// <param name="loginName">The name of the login that is created.</param>
        /// <param name="password">The password for the login that is being created.</param>
        /// <param name="mustChange">If this value is true, SQL Server prompts the user for a new password the first time the new login is used.</param>
        public void CreateLogin(string loginName, string password, bool mustChange)
        {
            CreateLogin(loginName, password, mustChange, null);
        }

        /// <summary>
        /// Creates a new SQL Server login.
        /// </summary>
        /// <param name="loginName">The name of the login that is created.</param>
        /// <param name="password">The password for the login that is being created.</param>
        /// <param name="mustChange">If this valus is true, SQL Server prompts the user for a new password the first time the new login is used.</param>
        /// <param name="defaultDatabase">The default database to be assigned to the login.</param>
        public void CreateLogin(string loginName, string password, bool mustChange, string defaultDatabase)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");
            if (password == null)
                throw new ArgumentNullException("password");
            
            //Escape and trim the roleName
            loginName = loginName.Trim().Replace("]", "]]");
            password = password.Replace("'", "''");
            if (!String.IsNullOrEmpty(defaultDatabase))
                defaultDatabase = defaultDatabase.Replace("]", "]]");

            //Build the sql
            string cmdText = String.Format(CultureInfo.InvariantCulture, "CREATE LOGIN [{0}] WITH PASSWORD = '{1}'", new string[] {loginName, password});
            if (mustChange)
                cmdText += " MUST_CHANGE";

            if (!String.IsNullOrEmpty(defaultDatabase))
                cmdText += String.Format(CultureInfo.InvariantCulture, ", DEFAULT_DATABASE=[{0}]", defaultDatabase);

            //If mustChange is true then we have to have CHECK_EXPIRATION & CHECK_POLICY set to true
            if (mustChange)
                cmdText += ", CHECK_EXPIRATION=ON, CHECK_POLICY=ON";
            
            _sqlDataWrapper.ExecuteNonQuery(cmdText);
        }

        /// <summary>
        /// Removes a SQL Server login account.
        /// </summary>
        /// <param name="loginName">The name of the login to be dropped.</param>
        public void DropLogin(string loginName)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");

            //Escape and trim the loginName
            loginName = loginName.Trim().Replace("]", "]]");

            //Build the sql
            string cmdText = String.Format(CultureInfo.InvariantCulture, "DROP LOGIN [{0}]", loginName);

            _sqlDataWrapper.ExecuteNonQuery(cmdText);
        }

        public void ResetPassword(string loginName, string newPassword)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");
            if (newPassword == null)
                throw new ArgumentNullException("newPassword");

            //Escape and trim the loginName
            loginName = loginName.Trim().Replace("]", "]]");
            newPassword = newPassword.Replace("'", "''");

            //Build the sql
            string cmdText = String.Format(CultureInfo.InvariantCulture, "ALTER LOGIN [{0}] WITH PASSWORD='{1}'", loginName, newPassword);

            _sqlDataWrapper.ExecuteNonQuery(cmdText);
        }

        public void ChangePassword(string loginName, string currentPassword, string newPassword)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");
            if (currentPassword == null)
                throw new ArgumentNullException("currentPassword");
            if (newPassword == null)
                throw new ArgumentNullException("newPassword");

            //Escape and trim the loginName
            loginName = loginName.Trim().Replace("]", "]]");
            currentPassword = currentPassword.Replace("'", "''");
            newPassword = newPassword.Replace("'", "''");

            //Build the sql
            string cmdText = String.Format(CultureInfo.InvariantCulture, "ALTER LOGIN [{0}] WITH PASSWORD='{1}' OLD_PASSWORD='{2}'", loginName, newPassword, currentPassword);

            _sqlDataWrapper.ExecuteNonQuery(cmdText);
        }

        public void Enable(string loginName)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");

            //Escape and trim the loginName
            loginName = loginName.Trim().Replace("]", "]]");

            //Build the sql
            string cmdText = String.Format(CultureInfo.InvariantCulture, "ALTER LOGIN [{0}] ENABLE", loginName);

            _sqlDataWrapper.ExecuteNonQuery(cmdText);
        }

        public void Disable(string loginName)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");

            //Escape and trim the loginName
            loginName = loginName.Trim().Replace("]", "]]");

            //Build the sql
            string cmdText = String.Format(CultureInfo.InvariantCulture, "ALTER LOGIN [{0}] DISABLE", loginName);

            _sqlDataWrapper.ExecuteNonQuery(cmdText);
        }

        /// <summary>
        /// Adds a login as a member of a fixed server role.
        /// </summary>
        /// <param name="loginName">The name of the login being added to the fixed server role. login is sysname, with no default. login can be a SQL Server login or a Windows login.</param>
        /// <param name="fixedServerRole">The name of the fixed server role to which the login is being added.</param>
        public void AddServerRoleMember(string loginName, FixedServerRole fixedServerRole)
        {
            if (loginName == null)
                throw new ArgumentNullException("loginName");

            //Escape and trim the loginName
            loginName = loginName.Trim();
            
            //Build the sql
            List<SqlParameter> parameters = new List<SqlParameter>();
            parameters.Add(new System.Data.SqlClient.SqlParameter("@loginame", loginName));
            parameters.Add(new System.Data.SqlClient.SqlParameter("@rolename", fixedServerRole.ToString().ToUpperInvariant()));

            _sqlDataWrapper.ExecuteNonQuery("sp_addsrvRoleMember", CommandType.StoredProcedure, parameters.ToArray());
        }
    }
}
